package com.cqut.service.impl;

import com.cqut.VO.result.ResultVO;
import com.cqut.entity.FileAttachment;
import com.cqut.entity.FileDirectory;
import com.cqut.mapper.FileMapper;
import com.cqut.service.FileService;
import com.cqut.util.ArgUtils;
import com.cqut.util.DateUtils;
import com.cqut.util.FileUtils;
import com.cqut.util.ResultVOUtil;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class FileServiceIml implements FileService {


    private FileMapper fileMapper;

    @Override
    public ResponseEntity<byte[]> downloadFile(String userName,String fileName) {
        if (ArgUtils.isHaveBlankArgs(userName,fileName)){
            return null;
        }

        ByteArrayOutputStream out = new ByteArrayOutputStream();

        try {
            String filePath = FileUtils.concatWithForwardSlash(FileUtils.getUploadFileDir(userName),fileName);

            File file = new File(filePath);

            if (!file.exists()){
                return null;
            }

            FileInputStream in = new FileInputStream(file);

            //缓存读取
            byte[] buffer = new byte[1024];

            int count = 0;

            while ((count = in.read(buffer)) !=-1){
                out.write(buffer,0,count);
            }

        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        byte[] byteStream =  out.toByteArray();

        //设置响应头
        HttpHeaders httpHeaders = new HttpHeaders();
        //通知浏览器以下载的方式打开文件
        httpHeaders.setContentDispositionFormData("attachment",fileName);
        //定义以流的形式下载返回文件数据
        httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);

        return new ResponseEntity<>(byteStream,httpHeaders, HttpStatus.OK);
    }

    @Override
    @Transactional(rollbackFor = IOException.class)
    public ResultVO<Boolean> uploadFile(MultipartFile file, String userName, String dirName) {

        //非空校验
        if (Objects.isNull(file) || Strings.isBlank(userName) || Strings.isBlank(dirName)){
            return ResultVOUtil.error("非法的参数");
        }

        File userDir = null;

        File userFile = null;

        //单位为kb
        Float fileSize = Float.parseFloat(String.valueOf(file.getSize())) / 1024;

        if (fileSize > 20 * 1024 * fileSize){
            return ResultVOUtil.error("文件过大,不得大于100M");
        }

        try {
            //基础文件目录路径
            String baseDirPath = FileUtils.getUploadFileDir(userName);

            //用户文件目录路径
            String userDirPath = FileUtils.concatWithForwardSlash(baseDirPath,dirName);

            //用户文件目录路径
            userDir = new File(userDirPath);

            //判断目录是否存在
            if (!userDir.exists() && !userDir.mkdirs()){
                return ResultVOUtil.error("目录创建失败");
            }else if (!userDir.isDirectory()){
                return ResultVOUtil.error("目录状态异常");
            }

            //获取原始文件名
            String fileName = file.getOriginalFilename();

            String filePath = FileUtils.concatWithForwardSlash(userDirPath,fileName);

            //用户文件路径
            userFile = new File(filePath);

            //如果文件已存在
            if (userFile.exists()){
                return ResultVOUtil.error("已存在同名文件");
            }

            //将文件复制到本地
            file.transferTo(userFile);

            //包装成 FileAttachment类
            FileAttachment uploadFile = new FileAttachment();

            //设置文件名
            uploadFile.setFileName(fileName);
            //上传者
            uploadFile.setUploader(userName);
            //父文件夹名
            uploadFile.setParentDirName(dirName);
            //完整路劲
            uploadFile.setFullPath(filePath);
            //创建时间
            uploadFile.setCreate_time(DateUtils.getTimeFormatNow());
            //更新时间
            uploadFile.setUpdate_time(DateUtils.getTimeFormatNow());

            //记入数据库
            if (getFileMapper().insetAFile(uploadFile).equals(0)){
                return ResultVOUtil.error("文件上传失败");
            }

        } catch (IOException e) {
            e.printStackTrace();
            FileUtils.deleteFile(userFile);
            return ResultVOUtil.error("文件上传失败");
        }

        return ResultVOUtil.success(true);
    }

    @Override
    public ResultVO<Boolean> createDir(String userName, String dirName,String parenDirName) {
        if (Strings.isBlank(userName) || Strings.isBlank(dirName) || Strings.isBlank(parenDirName)){
            return ResultVOUtil.error("非法的参数");
        }

        File dir = null;
        try {
            String preparedDirPath;

            //根据父目录是否为根目录来进行不同的拼接
            if (parenDirName.equals(FileUtils.ROOT)){
                preparedDirPath = FileUtils.concatWithForwardSlash(FileUtils.getUploadFileDir(userName),dirName);
            }else {
                preparedDirPath = FileUtils.concatWithForwardSlash(FileUtils.getUploadFileDir(userName),parenDirName,dirName);
            }

            //获取目录路径
            dir = new File(preparedDirPath);

            if (dir.exists()){
                return ResultVOUtil.error("已存在同名目录");
            }else if (!dir.mkdirs()){
                return ResultVOUtil.error("目录创建失败");
            }

            FileDirectory directory = new FileDirectory();

            //文件夹创建者
            directory.setCreator(userName);
            //文件夹名
            directory.setDirName(dirName);
            //父文件夹名
            directory.setParentDirName(parenDirName);
            //完整路径
            directory.setFullPath(preparedDirPath);

            directory.setCreate_time(DateUtils.getTimeFormatNow());

            directory.setUpdate_time(DateUtils.getTimeFormatNow());

            if (getFileMapper().createDir(directory).equals(0)){
                return ResultVOUtil.error("创建目录失败");
            }

        }catch (Exception e){
            e.printStackTrace();
            if (!Objects.isNull(dir)){
                FileUtils.deleteDirectory(dir);
            }
            return ResultVOUtil.error("创建目录失败");
        }

        return ResultVOUtil.success(true);
    }


    @Override
    public ResultVO<Boolean> deleteFile(String userName, String filePath,String fileName) {
        if (Strings.isBlank(userName) || Strings.isBlank(filePath)){
            return ResultVOUtil.error("非法的参数");
        }

        String fileURL = FileUtils.concatWithForwardSlash(FileUtils.getUploadFileDir(userName),filePath,fileName);

        File file = new File(fileURL);

        FileAttachment fileAttachment = new FileAttachment();

        fileAttachment.setFullPath(fileURL);

        if (!file.exists()){
            return ResultVOUtil.error("文件不存在");
        }

        if (getFileMapper().deleteAFile(fileAttachment).equals(0)){
            return ResultVOUtil.error("删除失败");
        }

        if (!FileUtils.deleteFile(file)){
           return ResultVOUtil.error("文件删除失败");
        }

        return ResultVOUtil.success(true);
    }

    @Override
    public ResultVO<Boolean> deleteDir(String userName, String dirName) {
        if (ArgUtils.isHaveBlankArgs(userName,dirName)){
            return ResultVOUtil.error("无效的参数");
        }

        String dirPath = FileUtils.concatWithForwardSlash(FileUtils.getUploadFileDir(userName),dirName);

        if (!FileUtils.deleteDirectory(dirPath)){
            return ResultVOUtil.error("删除失败");
        }else if ((getFileMapper().deleteDir(dirPath).equals(0))){
            return ResultVOUtil.error("删除失败");
        }

        return ResultVOUtil.success(true);
    }

    @Override
    public ResultVO<Boolean> moveIo(String userName, String originalDir, String replaceDir) {
        if (ArgUtils.isHaveBlankArgs(userName,originalDir,replaceDir)){
            return ResultVOUtil.error("无效的参数");
        }

        //旧路径
        String oldPath = FileUtils.concatWithForwardSlash(FileUtils.getUploadFileDir(userName),originalDir);

        //新路径
        String newPath = FileUtils.concatWithForwardSlash(FileUtils.getUploadFileDir(userName),replaceDir);

        File oldIO = new File(oldPath);

        File newIO = new File(newPath);

        if (!oldIO.exists()){
            return ResultVOUtil.error("原目录不存在");
        }

        if (newIO.exists()){
            return ResultVOUtil.error("已存在同名");
        }

        Integer impactCount = -1;

        if (oldIO.isFile()){
            impactCount = getFileMapper().updateFile(
                    newPath,
                    FileUtils.getParenPath(userName,newPath,newIO.getName()),
                    oldPath,
                    DateUtils.getTimeFormatNow()
            );

        }else if (oldIO.isDirectory()){

            impactCount = getFileMapper().updateDir(
                    newIO.getName(),
                    newPath,
                    DateUtils.getTimeFormatNow(),
                    FileUtils.getParenPath(userName,newPath,newIO.getName()),
                    oldPath
            );
        }

        if (impactCount.equals(0)){
            return ResultVOUtil.error("操作失败");
        }

        if (!oldIO.renameTo(newIO)){
            return ResultVOUtil.error("操作失败");
        }

        return ResultVOUtil.success(true);
    }

    @Override
    public ResultVO<List<FileAttachment>> getFileList(String userName, String dirName) {
        if (ArgUtils.isHaveBlankArgs(userName,dirName)){
            return ResultVOUtil.error("无效的参数");
        }

        List<FileAttachment> list = getFileMapper().getFileList(dirName,userName);

//        //过滤
//        list = list.stream().filter(fileDirectory -> dirName.equals(fileDirectory.getParentDirName())).collect(Collectors.toList());

        return ResultVOUtil.success(list);
    }

    @Override
    public ResultVO<List<FileDirectory>> getDirList(String userName, String dirName) {
        if (ArgUtils.isHaveBlankArgs(userName,dirName)){
            return ResultVOUtil.error("无效的参数");
        }

        List<FileDirectory> list = getFileMapper().getDirList(dirName,userName);

//        //过滤
//        list = list.stream().filter(fileDirectory -> dirName.equals(fileDirectory.getParentDirName())).collect(Collectors.toList());

        return ResultVOUtil.success(list);
    }

    @Autowired
    public void setFileMapper(FileMapper fileMapper) {
        this.fileMapper = fileMapper;
    }

    public FileMapper getFileMapper() {
        return fileMapper;
    }
}
